// @Author: cyl
// @File: withmap.go
// @Time: 2022/06/13 06:55:21
package main

import (
	"encoding/json"
	"fmt"
	"testing"

	"github.com/fatih/structs"
	"github.com/stretchr/testify/require"
)

/**
1. 常用思路：struct -> json -> map
2. struct -> map
*/

type StudentJsonMap struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Hobby string `json:"hobby"`
}

// structs嵌套结构体
type StudentJsonMapInherit struct {
	Name    string        `json:"name" structs:"name"`
	Age     int           `json:"age" structs:"age"`
	Profile ProfileStruct `json:"profile" structs:"profile"`
}

type ProfileStruct struct {
	Hobby  string `json:"hobby"`
	Gender int    `json:"gender" structs:"gender"` // 0 male 1female
}

func Test1(t *testing.T) {
	// 1. 第一种方式
	// 坑：value的类型会被改变
	s1 := StudentJsonMap{
		Name:  "whw",
		Age:   18,
		Hobby: "football",
	}
	// struct to json
	jsonRet, jsonError := json.Marshal(s1)
	require.Equal(t, jsonError, nil)
	fmt.Println("jsonRet:", jsonRet)

	// json to map
	var mapRet map[string]interface{}
	errUnMarshal := json.Unmarshal(jsonRet, &mapRet)
	require.Equal(t, errUnMarshal, nil)
	fmt.Println("mapRet:", mapRet)

	for key, val := range mapRet {
		fmt.Printf("key=%s, value=%s, valueOfType=%T\n", key, val, val)
	}
}

func Test2(t *testing.T) {
	// 2. 第二种方式-普通结构体: go get -u github.com/fatih/structs
	/**
	·可以在结构体中定义类型·
	type StudentJsonMap struct {
		Name  string `json:"name" structs:"user_name"`
		Age   int    `json:"age" structs:"user_age"`
		Hobby string `json:"hobby" structs:"user_hobby"`
	}
	*/
	s1 := StudentJsonMap{
		Name:  "whw",
		Age:   18,
		Hobby: "football",
	}
	mapRet := structs.Map(&s1)
	fmt.Println("mapRet:", mapRet)

	for key, val := range mapRet {
		fmt.Printf("key=%s, value=%s, valueOfType=%T\n", key, val, val)
	}
}

func Test3(t *testing.T) {
	// 3. 第二种方式-结构体嵌套: go get -u github.com/fatih/structs
	s1 := StudentJsonMapInherit{
		Name: "whw",
		Age:  18,
		Profile: ProfileStruct{
			Hobby:  "ball",
			Gender: 0,
		},
	}
	mapRet := structs.Map(&s1)
	fmt.Println("mapRet:", mapRet)

	for key, val := range mapRet {
		fmt.Printf("key=%s, value=%s, valueOfType=%T\n", key, val, val)
	}
}
